import json

from flask import request, jsonify
from flask_login import login_required
import secrets

from conf.flask_ini import FlaskIni
from conf.redis_cnx import RedisCnxPool
from service.user_role import UserRole
from web.const import StatusCode
from web.const import CONTEXT
from web.validation import valid

redis_conn = RedisCnxPool().get_conn()

app = FlaskIni().get_app()
rbac = FlaskIni().get_rbac()

prefix = f'{CONTEXT}/auth'


@app.route(f'{prefix}/login', methods=['POST'])
@rbac.allow(roles=['anonymous'], methods=['POST'])
def login():
    try:
        username = request.json['username']
        password = request.json['password']

        valid(username, password)

        user_info = UserRole.query_user_info(username)

        if user_info and password == user_info['password']:
            role_name = user_info['role_name']

            generated_api_key = 'CDSS-LOGIN-' + secrets.token_urlsafe(48)

            # expire time is 7 days
            redis_conn.set(name=generated_api_key,
                           value=json.dumps({'username': username, 'role_name': role_name}, ensure_ascii=False),
                           ex=3600 * 24 * 7)

            return jsonify({'status': StatusCode.SUCCESS_CODE,
                            'message': '',
                            'payload': {'api_key': generated_api_key}})
        else:
            raise
    except:
        return jsonify({'status': StatusCode.FAILURE_CODE, 'message': 'Bad Login', 'payload': ''})


@app.route(f'{prefix}/who_am_i', methods=['POST'])
@rbac.allow(roles=['小萌新'], methods=['POST'])
@login_required
def who_am_i():
    api_key = request.headers.get('Authorization')

    valid(api_key)

    json_data = json.loads(redis_conn.get(api_key))
    return jsonify({'status': StatusCode.SUCCESS_CODE, 'message': '', 'payload': json_data})


@app.route(f'{prefix}/logout', methods=['POST'])
@rbac.allow(roles=['anonymous'], methods=['POST'])
@login_required
def logout():
    api_key = request.headers.get('Authorization')

    valid(api_key)

    redis_conn.delete(api_key)
    return jsonify({'status': StatusCode.SUCCESS_CODE, 'message': 'Successfully logged out', 'payload': ''})


@app.route(f'{prefix}/user', methods=['POST'])
@rbac.allow(roles=['小萌新'], methods=['POST'])
@login_required
def user():
    return jsonify({'status': StatusCode.SUCCESS_CODE, 'message': '小萌新权限', 'payload': ''})


@app.route(f'{prefix}/editor', methods=['POST'])
@rbac.allow(roles=['编辑员'], methods=['POST'])
@login_required
def editor():
    return jsonify({'status': StatusCode.SUCCESS_CODE, 'message': '小萌新和编辑员权限', 'payload': ''})


@app.route(f'{prefix}/super', methods=['POST'])
@rbac.allow(roles=['审查员'], methods=['POST'])
@login_required
def super():
    return jsonify({'status': StatusCode.SUCCESS_CODE, 'message': '小萌新和审查员权限', 'payload': ''})


@app.route(f'{prefix}/admin', methods=['POST'])
@rbac.allow(roles=['管理员'], methods=['POST'])
@login_required
def admin():
    return jsonify({'status': StatusCode.SUCCESS_CODE, 'message': '上帝权限', 'payload': ''})
